package nina.yiyou.performance.s10init.output

import nina.yiyou.performance.s20confirm.output.PerformGeneratePreparer
import nina.yiyou.salary.output.util.CsvLineMaker
import nina.yiyou.salary.output.util.KeyCellReader
import nina.yiyou.salary.output.util.OutCsvWriter
import org.apache.poi.ss.usermodel.Row
import org.apache.poi.ss.usermodel.Sheet

import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.StandardCopyOption

// 绩效待填
class PerformFillGenerator {

  PerformFillGenerator(Path templatePath, List<Map> employeeResults, Path outDir, Path tmpDir) {
    _templatePath = templatePath
    _employeeResults = employeeResults
    _outDir = outDir
    _tmpDir = tmpDir
  }

  void generate() {
    def (List resultKeys, List nameKeys) = new PerformGeneratePreparer<List<List>>(
        _templatePath, this.&readKeys, _outDir, _tmpDir).prepare()

    List<Evaluator> evalList = _employeeResults.collect { makeEvaluator(it) }
    evalList.each { generateEvaluateeV2(it, resultKeys, nameKeys) }

    new OutCsvWriter(_tmpDir.resolve('0.csv'), evalList
        .collect { [it.excelPathV2(), it.csvPathV2()] }
        .collect { new CsvLineMaker(it).make() }).write()
  }

  private List<List<String>> readKeys(Sheet sheet) {
    def rowToKey = { int row ->
      Row r = sheet.getRow(row)
      return (0..<r.lastCellNum).collect { new KeyCellReader(r.getCell(it)).read() }
    }
    return (0..1).collect { rowToKey.call(it) }
  }

  private Evaluator makeEvaluator(Map<String, ?> employee) {
    String basicPrefix = employee.keySet()
        .findAll { it.endsWith('.工号') }
        .collect { it.split(/\./) }
        .findAll { it.size() == 2 }
        .take(1)[0][0]

    def toKey = { String k -> "${basicPrefix}.${k}".toString() }
    def dirName = { Map e ->
      ['部门', '工号', '姓名']
          .collect { e[toKey.call(it)] }
          .join('_')
    }

    def employeeId = { Map e -> e[toKey.call('工号')] }
    def ee = { Map e ->
      return new Evaluatee() {
        @Override
        String employeeId() {
          return employeeId.call(e)
        }

        @Override
        Map<String, ?> data() {
          return e
        }
      }
    }

    return new Evaluator() {
      @Override
      Map data() {
        return employee
      }

      @Override
      Path excelPathV2() {
        return _outDir.resolve(dirName.call(employee) + '.xlsx')
      }

      @Override
      Path csvPathV2() {
        return _tmpDir.resolve(dirName.call(employee) + '.csv')
      }

      @Override
      List<Evaluatee> evaluateeList() {
        String evaluatorId = employeeId.call(employee)
        return _employeeResults
            .collect { ee.call(it) }
            .findAll { evaluatorId != it.employeeId() }
            .sort { it.data()[toKey.call('部门')] }
      }
    }
  }

  private void generateEvaluateeV2(Evaluator eval, List<String> resultKeys, List<String> nameKeys) {
    Path excelPath = eval.excelPathV2()
    copyFile(_templatePath, excelPath)

    Path csvPath = eval.csvPathV2()
    println("生成 -> ${csvPath}")

    def makeHeader = { Map data -> nameKeys.collect { data[it] }.join('_') }
    new OutCsvWriter(csvPath, [
        resultKeys.collect { eval.data()[it] },
        eval.evaluateeList().collect { makeHeader.call(it.data()) },
    ].collect { new CsvLineMaker(it).make() }).write()
  }

  private void copyFile(Path from, Path to) {
    Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING)
  }

  interface Evaluator {

    Map data()

    Path excelPathV2()

    Path csvPathV2()

    List<Evaluatee> evaluateeList()
  }

  interface Evaluatee {

    String employeeId()

    Map<String, ?> data()
  }

  private final Path _templatePath
  private final List<Map> _employeeResults

  private final Path _outDir
  private final Path _tmpDir
}
